// test_flex_allocator.c - Simplified version
#include "test_framework.h"
#include "../hisi_l0_mem_pool.h"
#include "test_common.h"
#include "test_registration.h"

/**
 * test_flex_allocator_boundary - Tests flex_allocator boundary conditions
 * 
 * This test verifies:
 * 1. Allocation of objects exactly at the boundary between Fix Allocator and flex_allocator
 * 2. Allocation of objects just above MAX_FIX_ALLOCATOR_SIZE
 * 3. Proper handling of flex_allocator allocations through public API
 * 
 * Tests boundary conditions for the transition from Fix Allocator to flex_allocator
 */
static int test_flex_allocator_boundary(struct seq_file *m)
{
    struct test_context *ctx = get_test_context();
    void *ptr1, *ptr2;
    int passed = 0, total = 0;
    
    // Test allocation exactly at MAX_FIX_ALLOCATOR_SIZE (should use Fix Allocator)
    total++;
    ptr1 = l0_kmalloc(MAX_FIX_ALLOCATOR_SIZE, ctx->test_node_id);
    if (ptr1) {
        // Verify memory is accessible and can be written to
        memset(ptr1, 0xAA, MAX_FIX_ALLOCATOR_SIZE);
        l0_kfree(ptr1);
        TEST_PASS(m, "Boundary allocation at MAX_FIX_ALLOCATOR_SIZE (%d bytes) successful", MAX_FIX_ALLOCATOR_SIZE);
        passed++;
    } else {
        TEST_FAIL(m, "Boundary allocation at MAX_FIX_ALLOCATOR_SIZE (%d bytes) failed", MAX_FIX_ALLOCATOR_SIZE);
    }
    
    // Test allocation just above MAX_FIX_ALLOCATOR_SIZE (should use flex_allocator)
    total++;
    ptr2 = l0_kmalloc(MAX_FIX_ALLOCATOR_SIZE + 1, ctx->test_node_id);
    if (ptr2) {
        // Verify memory is accessible and can be written to
        memset(ptr2, 0xBB, MAX_FIX_ALLOCATOR_SIZE + 1);
        l0_kfree(ptr2);
        TEST_PASS(m, "flex_allocator allocation just above MAX_FIX_ALLOCATOR_SIZE (%d bytes) successful", MAX_FIX_ALLOCATOR_SIZE + 1);
        passed++;
    } else {
        TEST_FAIL(m, "flex_allocator allocation just above MAX_FIX_ALLOCATOR_SIZE (%d bytes) failed", MAX_FIX_ALLOCATOR_SIZE + 1);
    }
    
    TEST_END(m, "Flex Allocator boundary tests: %d/%d passed", passed, total);
    return (passed == total) ? 0 : -1;
}

/**
 * test_flex_allocator_large_allocations - Tests large flex_allocator allocations
 * 
 * This test verifies:
 * 1. Allocation of very large objects using flex_allocator
 * 2. Memory accessibility for large flex_allocator-allocated memory
 * 3. Proper cleanup of large flex_allocator-allocated memory blocks
 * 
 * Tests large object allocation through the flex_allocator
 */
static int test_flex_allocator_large_allocations(struct seq_file *m)
{
    struct test_context *ctx = get_test_context();
    void *ptr;
    size_t large_sizes[] = {16384, 65536, 262144}; // 16KB, 64KB, 256KB
    int i;
    int passed = 0, total = 0;
    
    for (i = 0; i < ARRAY_SIZE(large_sizes); i++) {
        total++;
        ptr = l0_kmalloc(large_sizes[i], ctx->test_node_id);
        if (ptr) {
            // Test access to first and last pages
            memset(ptr, 0xCC, 4096); // First page
            memset((char*)ptr + large_sizes[i] - 4096, 0xDD, 4096); // Last page
            l0_kfree(ptr);
            TEST_PASS_DEBUG(m, "Large flex_allocator allocation %zu bytes successful", large_sizes[i]);
            passed++;
        } else {
            TEST_FAIL(m, "Large flex_allocator allocation %zu bytes failed", large_sizes[i]);
        }
    }
    
    TEST_END(m, "Large flex_allocator allocation tests: %d/%d passed", passed, total);
    return (passed == total) ? 0 : -1;
}

// Export test cases
static struct test_case test_flex_allocator_cases[] = {
    {"Flex Allocator Boundary Conditions", test_flex_allocator_boundary},
    {"Flex Allocator Large Allocations", test_flex_allocator_large_allocations},
};

DECLARE_TEST_MODULE(flex_allocator, test_flex_allocator_cases)